home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / info-service / gopher / Unix / GopherTools / metaclone < prev    next >
Encoding:
Text File  |  1993-06-15  |  6.4 KB  |  184 lines

  1. #!/usr/local/bin/perl
  2. # metaclone - clone gophers
  3.  
  4. # usage:
  5. # metaclone [www style gopher reference]
  6. # metaclone gopher://gopher.msen.com:70/cicnet
  7.  
  8. # original NNTP client suggested by eci386!clewis
  9. # socket code mailed to me by cmf@obie.cis.pitt.edu (Carl M. Fongheiser)
  10. # adaptation for gopher by emv@msen.com (Edward Vielmetti)
  11. # modification to indexer by alberti@boombox.micro.umn.edu (Bob Alberti)
  12. # Hacked into metaclone by benseb@sdsc.edu ( Booker C. Bense ) 11/2/92
  13. # This was tested with perl.4.19
  14. # Note: this assumes it is running in the directory underneath which
  15. # you want the metacenter info to appear, i.e. At SDSC we would run 
  16. # it in the MetaCenter directory. 
  17.  
  18. # Configuration information -- change to reflect your site.
  19.  
  20. $_ = $ARGV[0] ? $ARGV[0] : 'gopher://darth.sdsc.edu:70/1MetaCenter';
  21. $my_host = "grumpy.sdsc.edu" ;  # who is my gopher server 
  22.                 # Might be the same as hostname
  23. #If an argument exists, use it, otherwise use default
  24.  
  25. ($service, $host, $port, $path) = (/^(gopher:\/\/)([^:]+):(\d+)\/.\/(.*)/); 
  26.  
  27. #If debug = 0, metaclone runs silent.  =1 is a verbose run.  Commented
  28. #debug lines are annoyingly thorough
  29.  
  30. $DEBUG = 1;              #set this to 0 for silent operation
  31.  
  32. # stuff for recursion levels and their_host
  33.  
  34. $last_level = 2 ;        # directories are links at this level
  35. $too_deep = $last_level ;    # Don't go greater than this level 
  36.  
  37.  
  38. if ($host && $port && $path) {
  39.     $DEBUG && print "host=$host; port=$port; path=$path\n";
  40.     # Here's how to make your own socket.ph
  41.     # cp /usr/include/sys/socket.h socket.h
  42.     # h2ph socket
  43.     require 'sys/socket.ph';    
  44.     chop($hostname = `hostname`); # get host name in variable
  45.  
  46.     $their_host = $host ;    # Remember original host !
  47.     ($N) = &tcpconnect($host, $hostname);# open connection 
  48.     if ($path eq "/") {
  49.         $path = "";
  50.     }
  51.     $recurse_level = 0; 
  52.     &gopherlevel($host, $hostname, $path, N); # clone the gopher
  53.  
  54.     close(N);            # close the connection.  NOTHING TO IT!
  55. }
  56. else {
  57.    print "Command format:\n\n";
  58.    print "   metaclone service://host.name:port/path/\n\n";
  59.    print "If a directory in the path includes multiple words separated by spaces,\n";
  60.    print "(i.e. /path name/), surround the parameter string with single quotes:\n\n";
  61.    print "   metaclone 'service://host.name:port/path name/'\n\n";
  62.  
  63. }
  64.  
  65. sub gopherlevel {  
  66.          
  67.  
  68.    # Build a level of gopher directory before recursion
  69.    local($host, $hostname, $path, $N) = @_;
  70.                            $DEBUG && print "sending path=$path\n";
  71.  
  72.    $recurse_level += 1;        # Actually this is not needed, but I'm paranoid
  73.     if ( $recurse_level  > $too_deep ) {
  74.         $DEBUG && print "Recurse Level too deep $recurse_level\n";
  75.         return ; 
  76.     }
  77.  
  78.    $path =~ s%^/(\d+)%\1/%; #swap first / and char ( Must have type!)
  79.    send(N,"$path\r\n",0);
  80.                            $DEBUG && print STDERR "$path\r\n";
  81.    local($dirnum, $docnum, $i, @doc, @dir); #avoid scoping errors
  82.    @doc = 0;               #call me a fuddy-duddy but I like to Know
  83.    @dir = 0;
  84.    $filename = sprintf(".Remote@%s",$host); 
  85.    open(FILE, ">>$filename") || die "Couldn't open new file $filename: $!\n";
  86.    while(<N>)  {        #While receiving data
  87.        chop;chop;        # trim data
  88.        next if /^[\. ]*$/;    # quit if a period
  89.        s/^(.)// && ( $type = $1); # otherwise Type is first character
  90.        @G= split(/\t/);        # and split other fields on tabs
  91.  
  92.  
  93.  
  94.        if (($type == 1 && $recurse_level < $last_level ) && $G[2] eq $their_host )  {    
  95. # Add directories to the list of directories
  96.        $dirnum += 1;
  97.        $dir[$dirnum] = $G[1]; # to be built after all information received
  98.        $DEBUG && print "$dirnum: $dir[$dirnum]\n";   
  99. # need to make .cap entries .... 
  100.        @path = split('/',$dir[$dirnum]); # split off leading entries in path;
  101.        $dirname = $path[$#path]; # take last item as name
  102.  
  103.        $_ = $dirname;    #Bah, this is ungraceful, but 
  104.        if (/^\S/) {        #sometimes $dirname is blank.
  105.            if ( ! -d ".cap" ) {
  106.            mkdir (".cap", 0xfff ) || print  "Mkdir .cap: $!\n"; }
  107.            if ( ! -f ".cap/$dirname" ) {
  108.            open(CAPFILE, ">.cap/$dirname") 
  109.                || die "Couldn't open new file .cap/$dirname: $!\n";
  110.            print CAPFILE "Name=$G[0]\n" ;
  111.            close(CAPFILE); }
  112.        } ; 
  113.        } else {
  114.        if ( $G[2] ne $my_host ) { # Should check for redundant entries here !
  115.            #  Something for the next version BCB 11/2/92 
  116.            #  The server is smart enough in version 1.03 to
  117.            #  not print redundant entries
  118.            print FILE "#\nType=$type\n";
  119.            print FILE "Name=$G[0]\n";
  120.            print FILE "Path=$G[1]\n";
  121.            print FILE "Host=$G[2]\n";
  122.            print FILE "Port=$G[3]\n";
  123.        } else {
  124.            $DEBUG && print "@G is :$my_host:$G[2]: \n"; }
  125.        }
  126.    }
  127.    close(FILE);
  128.    
  129.    close(N);
  130.  
  131.    for ($i = 1; $i <= $dirnum; $i++) {  # Make directories
  132.        @path = split('/',$dir[$i]);     # split off leading entries in path;
  133.        $dirname = $path[$#path];        # take last item as name
  134.        $DEBUG && print "dirname: $dirname\n";
  135.        $_ = $dirname;                #Bah, this is ungraceful, but 
  136.        if (/^\S/) {                #sometimes $dirname is blank.
  137.        if ( ! -d $dirname ) {
  138.            mkdir ($dirname, 0xfff) || print "Mkdir $dirname: $!\n"; }
  139.        }
  140.        else {
  141.            next;
  142.        }
  143.        chdir ($dirname)        || die print "Chdir $dirname: $!\n";
  144.  
  145.        $DEBUG && print "Connecting to $host from $hostname\n"; 
  146.        ($N) = &tcpconnect($host, $hostname);
  147.  
  148.        if ($N) {
  149.        &gopherlevel($host, $hostname, $dir[$i], N);
  150.        $recurse_level -= 1; # pop recurse_level on return 
  151.        sleep(2);        #arbitrary sleeps give sockets time to close
  152.        chdir("..")          || die print "chdir up: $!\n"; 
  153.        }
  154.        else {
  155.        die "Couldn't open tcp connection $N: $!\n"; 
  156.        }
  157.        close(N);
  158.    }  
  159. }
  160.  
  161. sub tcpconnect {                    #Get TCP info in place
  162.    local($host, $hostname) = @_;
  163.    $sockaddr = 'S n a4 x8';
  164.  
  165.                             #$DEBUG && print "host: $host, me: $hostname\n";
  166.  
  167.    ($name,$aliases,$proto) = getprotobyname('tcp');
  168.    ($name,$aliases,$port) = getservbyname($port, 'tcp')
  169.         unless $port =~ /^\d+$/;
  170.    ($name,$aliases,$type,$len,$thisaddr) = gethostbyname($hostname);
  171.    ($name,$aliases,$type,$len,$thataddr) = gethostbyname($host);
  172.  
  173.    $this = pack($sockaddr, &AF_INET, 0, $thisaddr);
  174.    $that = pack($sockaddr, &AF_INET, $port, $thataddr);
  175.  
  176.    sleep(2);
  177.  
  178.    socket(N, &PF_INET, &SOCK_STREAM, $proto) || die "socket: $!";
  179.    bind(N, $this)                            || die "bind: $!";
  180.    connect(N, $that)                         || die "connect: $!";
  181.  
  182.    return(N);
  183. }
  184.